package com.accedo.achievements.services.ajax.impl;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.accedo.achievements.dataaccess.dao.impl.CampaignDaoImpl;
import com.accedo.achievements.dataaccess.dao.impl.UserDaoImpl;
import com.accedo.achievements.dataaccess.model.Campaign;
import com.accedo.achievements.dataaccess.model.User;
import com.accedo.achievements.services.ajax.CampaignService;

/**
 * The business logic service of Campaign relevant functionality
 * @author Bo Liang
 */
@Component
public class CampaignServiceImpl implements CampaignService {
	
	private static final Logger log = LoggerFactory.getLogger(BadgeServiceImpl.class);

	private User user; //injection
	private Campaign camp; //injection
	
	private UserDaoImpl userDao; //injection
	private CampaignDaoImpl campDao; //injection
	
	// Constructor
	CampaignServiceImpl() {}; 

	/**
	 * Get all campaigns in three state categories : finished, playing and none.
	 * <p>the sequence is grouped by the latest campaign to the front.
	 * <p>finished state means this user already unlocked all achievements and obtained the award of this campaign.<br>
	 * playing state means this user has at least unlocked one of the achievements, but has not obtained the award.<br>
	 * none state means this user has never unlocked any achievements related to the campaign.
	 * @param username	user name
	 * @return			JSON campaigns<br>
	 * eg. {camps:[{camp_sn:'CAMP011', camp_name:'CAMP011 NAME', camp_end:'2012.08.09 Thu 12:00', state:'playing'},
	 * {camp_sn:'CAMP010', camp_name:'CAMP010 NAME', camp_end:'2012.08.08 Wed 00:00', state:'none'}]}
	 */
	public JSONObject getJsonCampsByUsername(String username) {
		log.debug("### Entering getJsonCampsByUsername(username = {})", username);
		List<Campaign> campList = new ArrayList<Campaign>(); 
		JSONObject jsonObject = new JSONObject();
		JSONArray jsonArray = new JSONArray();
		Map<Integer, String> unlockedCampIdMap = new HashMap<Integer, String>();
		String state = "none";
		user = userDao.getUserByUsername(username);
		// get all available campaigns to the campaign List
		campList = campDao.getAvailableCampList();
		// get user unlocked campaigns id to the unlocked campaign id list
		unlockedCampIdMap = campDao.getActiveCampIdMapByUserId(user.getId());
		Format dateFormat = new SimpleDateFormat("yyyy.MM.dd E HH:mm");
		for (Iterator<Campaign> iter = campList.iterator(); iter.hasNext(); ) {
			camp = iter.next();
			if (unlockedCampIdMap.containsKey(camp.getId())) {
				state = unlockedCampIdMap.get(camp.getId());
			} else {
				state = "none";	
			}
			jsonObject.element("camp_sn", camp.getCamp_sn()); 
			jsonObject.element("camp_name", camp.getCamp_name());
			jsonObject.element("camp_end", dateFormat.format(camp.getCamp_end()));
			jsonObject.element("state", state);
			jsonArray.add(jsonObject);
			jsonObject.clear();
			
		}
		jsonObject.element("camps", jsonArray);
		try {
			Thread.sleep(2200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		log.debug("### Leaving getJsonCampsByUsername() : {}", jsonObject);
		return jsonObject; 	
	}
	
	/**
	 * Get all campaigns in three state categories : finished, playing and none.
	 * <p>the sequence is grouped by finished campaign, playing campaign and then none campaign.
	 * <p>finished state means this user already unlocked all achievements and obtained the award of this campaign.<br>
	 * playing state means this user has at least unlocked one of the achievements, but has not obtained the award.<br>
	 * none state means this user has never unlocked any achievements related to the campaign.
	 * @param username	user name
	 * @return			JSON campaigns<br>
	 * eg. {camps:[{camp_sn:'CAMP011', camp_name:'CAMP011 NAME', camp_end:'2012.08.09 Thu 12:00', state:'finished'},
	 * {camp_sn:'CAMP002', camp_name:'CAMP002 NAME', camp_end:'2012.08.01 Wed 00:00', state:'playing'},
	 * {camp_sn:'CAMP010', camp_name:'CAMP010 NAME', camp_end:'2012.08.08 Wed 00:00', state:'none'}]}
	 */
	public JSONObject getJsonCampsByUsernameForFriendShow(String username) {
		log.debug("### Entering getJsonCampsByUsernameForFriendShow(username = {})", username);
		List<Campaign> campList = new ArrayList<Campaign>(); 
		Map<Integer, String> unlockedCampIdMap = new HashMap<Integer, String>();
		String state = "none";
		JSONObject jsonObject = new JSONObject();
		JSONArray jsonArray = new JSONArray();
		JSONArray jsonArrayFinished = new JSONArray();
		JSONArray jsonArrayPlaying = new JSONArray();
		JSONArray jsonArrayNone = new JSONArray();
		user = userDao.getUserByUsername(username);
		// get all available campaigns to the campaign List
		campList = campDao.getAvailableCampList();
		// get user unlocked campaigns id to the unlocked campaign id list
		unlockedCampIdMap = campDao.getActiveCampIdMapByUserId(user.getId());
		
		Format dateFormat = new SimpleDateFormat("yyyy.MM.dd E HH:mm");
		
		for (Iterator<Campaign> iter = campList.iterator(); iter.hasNext(); ) {
			camp = iter.next();
			jsonObject.element("camp_sn", camp.getCamp_sn()); 
			jsonObject.element("camp_name", camp.getCamp_name()); 
			jsonObject.element("camp_end", dateFormat.format(camp.getCamp_end()));
			
			if (unlockedCampIdMap.containsKey(camp.getId())) {
				state = unlockedCampIdMap.get(camp.getId());
				if (state == "finished") {
					jsonObject.element("state", state); 
					jsonArrayFinished.add(jsonObject);
					
				} else if (state == "playing") {
					jsonObject.element("state", state); 
					jsonArrayPlaying.add(jsonObject);
				}
			} else {
				state = "none";
				jsonObject.element("state", state); 
				jsonArrayNone.add(jsonObject);
			}
			jsonObject.clear();
		}
		jsonArray.addAll(jsonArrayFinished);
		jsonArray.addAll(jsonArrayPlaying);
		jsonArray.addAll(jsonArrayNone); 
		jsonObject.element("camps", jsonArray);
		try {
			Thread.sleep(2200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		log.debug("### Leaving getJsonCampsByUsernameForFriendShow() : {}", jsonObject);
		
		return jsonObject; 	
	}

	public User getUser() {
		return user;
	}

	@Resource
	public void setUser(User user) {
		this.user = user;
	}

	public UserDaoImpl getUserDao() {
		return userDao;
	}

	@Resource
	public void setUserDao(UserDaoImpl userDao) {
		this.userDao = userDao;
	}

	public Campaign getCamp() {
		return camp;
	}

	@Resource
	public void setCamp(Campaign camp) {
		this.camp = camp;
	}

	public CampaignDaoImpl getCampDao() {
		return campDao;
	}

	@Resource
	public void setCampDao(CampaignDaoImpl campDao) {
		this.campDao = campDao;
	}
}
